import { useEffect, useRef, useCallback } from 'react'
import { useKafkaStore } from '@/stores/kafkaStore'
import toast from 'react-hot-toast'

interface WebSocketMessage {
  type: string
  topic?: string
  data?: any
  message?: string
  timestamp?: number
}

export function useWebSocket() {
  const ws = useRef<WebSocket | null>(null)
  const reconnectTimer = useRef<NodeJS.Timeout | null>(null)
  const reconnectAttempts = useRef(0)
  const maxReconnectAttempts = 5
  
  const { 
    setWsConnected, 
    addMessage, 
    wsConnected 
  } = useKafkaStore()

  const connect = useCallback(() => {
    if (ws.current?.readyState === WebSocket.OPEN) {
      return
    }

    try {
      const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
      const wsUrl = `${protocol}//${window.location.host}/ws/stream`
      
      ws.current = new WebSocket(wsUrl)

      ws.current.onopen = () => {
        console.log('WebSocket连接已建立')
        setWsConnected(true)
        reconnectAttempts.current = 0

        // 将WebSocket实例暴露到全局，供监控页面使用
        ;(window as any).ws = ws.current

        // 发送心跳
        const heartbeat = setInterval(() => {
          if (ws.current?.readyState === WebSocket.OPEN) {
            ws.current.send(JSON.stringify({
              type: 'ping',
              timestamp: Date.now()
            }))
          } else {
            clearInterval(heartbeat)
          }
        }, 30000)
      }

      ws.current.onmessage = (event) => {
        try {
          const message: WebSocketMessage = JSON.parse(event.data)
          
          switch (message.type) {
            case 'message':
              if (message.data) {
                addMessage(message.data)
              }
              break
              
            case 'subscribed':
              toast.success(`已订阅Topic: ${message.topic}`)
              break
              
            case 'unsubscribed':
              toast.success(`已取消订阅Topic: ${message.topic}`)
              break
              
            case 'error':
              toast.error(message.message || '发生错误')
              break
              
            case 'pong':
              // 心跳响应，不需要处理
              break

            case 'data_generator_progress':
              // 数据生成器进度消息，转发给全局处理
              console.log('数据生成进度:', message.data)
              break

            default:
              console.log('未知消息类型:', message.type)
          }
        } catch (error) {
          console.error('解析WebSocket消息失败:', error)
        }
      }

      ws.current.onclose = (event) => {
        console.log('WebSocket连接已关闭:', event.code, event.reason)
        setWsConnected(false)

        // 清理全局WebSocket引用
        ;(window as any).ws = null

        // 自动重连
        if (reconnectAttempts.current < maxReconnectAttempts) {
          reconnectAttempts.current++
          const delay = Math.min(1000 * Math.pow(2, reconnectAttempts.current), 30000)

          reconnectTimer.current = setTimeout(() => {
            console.log(`尝试重连 (${reconnectAttempts.current}/${maxReconnectAttempts})`)
            connect()
          }, delay)
        } else {
          toast.error('WebSocket连接失败，请刷新页面重试')
        }
      }

      ws.current.onerror = (error) => {
        console.error('WebSocket错误:', error)
        setWsConnected(false)
        // 清理全局WebSocket引用
        ;(window as any).ws = null
      }

    } catch (error) {
      console.error('创建WebSocket连接失败:', error)
      setWsConnected(false)
    }
  }, [setWsConnected, addMessage])

  const disconnect = useCallback(() => {
    if (reconnectTimer.current) {
      clearTimeout(reconnectTimer.current)
      reconnectTimer.current = null
    }

    if (ws.current) {
      ws.current.close()
      ws.current = null
    }

    // 清理全局WebSocket引用
    ;(window as any).ws = null

    setWsConnected(false)
  }, [setWsConnected])

  const sendMessage = useCallback((message: any) => {
    if (ws.current?.readyState === WebSocket.OPEN) {
      ws.current.send(JSON.stringify(message))
      return true
    }
    return false
  }, [])

  const subscribeTopic = useCallback((topic: string) => {
    return sendMessage({
      type: 'subscribe',
      topic
    })
  }, [sendMessage])

  const unsubscribeTopic = useCallback((topic: string) => {
    return sendMessage({
      type: 'unsubscribe',
      topic
    })
  }, [sendMessage])

  useEffect(() => {
    connect()
    
    return () => {
      disconnect()
    }
  }, [connect, disconnect])

  return {
    connected: wsConnected,
    connect,
    disconnect,
    sendMessage,
    subscribeTopic,
    unsubscribeTopic
  }
}
